package com.rongxue.service.Impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.rongxue.mapper.*;
import com.rongxue.pojo.*;
import com.rongxue.service.ProjectService;
import com.rongxue.service.SareaService;
import com.rongxue.service.utils.*;
import com.rongxue.utils.CommonUtils;
import com.rongxue.utils.DateUtil;

import com.rongxue.utils.HttpClientUtil;
import com.rongxue.utils.Page;
import net.sf.json.JSONArray;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.File;
import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;


@Service
@Transactional
public class ProjectServiceImpl implements ProjectService {

    @Autowired
    private SProjectMapper projectMapper;
    @Autowired
    private SUserMapper userMapper;
    @Autowired
    private SUserBankMapper userBankMapper;
    @Autowired
    private SInvestmentDetailMapper investmentDetailMapper;
    @Autowired
    private SUserRedenvelopeMapper userRedenvelopeMapper;//红包
    @Autowired
    private SUserInterestCouponMapper userInterestCouponMapper;

    @Autowired
    private SUserAccountMapper userAccountMapper;

    @Autowired
    private RecordsUtils recordsUtils;

    @Autowired
    private  SUserDueDetailMapper sUserDueDetailMapper;

   @Autowired
   private SUserWalletRecordsMapper sUserWalletRecordsMapper;

    //@Value("${MCHNT_CD}")
    public String MCHNT_CD = CashInAndOutServiceImpl.MCHNT_CD;//商户代码
    //@Value("${PAGE_NOTIFY_URL}")
    private String PAGE_NOTIFY_URL = CashInAndOutServiceImpl.PAGE_NOTIFY_URL;//商户回调地址
    //@Value("${P2P_SEND_MSG_URL}")
    private String P2P_SEND_MSG_URL = CashInAndOutServiceImpl.P2P_SEND_MSG_URL;//认证支付url
    //@Value("${KEY}")
    private String KEY = CashInAndOutServiceImpl.KEY;//密钥
    //@Value("${APP_MCHNT_CD}")
    public String APP_MCHNT_CD = CashInAndOutServiceImpl.APP_MCHNT_CD;//APP商户代码

    private static final Logger LOGGER = LoggerFactory.getLogger(ProjectService.class);


    //用户投资
    @Override
    public ObjectResult tender(XMLBean xmlBean) {

        ConcurrentHashMap<String, Long> map = new CashInAndOutServiceImpl().map;

        long time = System.currentTimeMillis();
        Long oldTime = map.put(xmlBean.getToken(), time);
        if (oldTime != null){
            if (time - oldTime < 3000){
                return ObjectResult.build("0", "请勿重复提交");
            }
        }

        String userId = CommonUtils.decToken(xmlBean.getToken());
        P2PMessageUtils p2PMessageUtils = new P2PMessageUtils();
        SUser resultUser =userMapper.selectUserInfoById(Long.parseLong(userId));
        if (resultUser == null){
            return ObjectResult.build("0", "用户信息错误,请重试");
        }

        //查询身份证是否被绑定
        if (resultUser.getCardNoAuth() == null || resultUser.getCardNoAuth() != 1) {
            return ObjectResult.build("0", "投资前请实名认证");
        }

        SUserBank sUserBank = userBankMapper.selectUserBankByUserId(userId);
        if (sUserBank == null){
            return ObjectResult.build("0", "投资前请绑定银行卡");
        }

        //标验证
        SProject project = projectMapper.selectByPrimaryKey(Long.parseLong(xmlBean.getProject_id()));
        if (project == null) {
            return ObjectResult.build("0", "标信息错误,请重试");
        }
        BigDecimal ableMoney = project.getAble();
        //如果此标的可投金额为0
        if (ableMoney.compareTo(new BigDecimal(0.00)) <= 0) {
            return ObjectResult.build("0", "此标已满", new ArrayList());
        }
        //用户想要投资的金额
        BigDecimal amount = new BigDecimal(xmlBean.getAmoney());
        //用户使用红包后的真实金额，如果没有使用红包则真实金额和想要投资金额一样
        BigDecimal realMoney = new BigDecimal(xmlBean.getMoney());

        BigDecimal limit = new BigDecimal(0);
        if (amount.compareTo(limit) <0){

            return ObjectResult.build("0", "低于最小投资金额");
        }else if (realMoney.compareTo(limit) < 0){

            return ObjectResult.build("0", "低于最小投资金额");
        }

        //用户投资金额要大于此标最小投资金额 小于最大投资金额
        BigDecimal minMoney = new BigDecimal(project.getMoney_min());
        BigDecimal maxMoney = new BigDecimal(project.getMoney_max());
        //如果最大的可投金额是0则不限制
        if (0 != maxMoney.doubleValue()) {
            if (amount.compareTo(maxMoney) <= 0) {
                //如果用户投资金额大于此标可投金额 则用户所投投金额变成标可投金额
                if (amount.compareTo(ableMoney) > 0) {
                    return ObjectResult.build("0", "投资金额大于此标的可投金额");
                }
            } else {
                return ObjectResult.build("0", "金额大于最大投资金额");
            }
        }
        if (amount.compareTo(minMoney) >= 0) {
            //如果用户投资金额大于此标可投金额 则用户所投投金额变成标可投金额
            if (amount.compareTo(ableMoney) > 0) {
                return ObjectResult.build("0", "投资金额大于此标的可投金额");
            }
        } else {
            return ObjectResult.build("0", "金额小于此标的投资金额");
        }

        //新手标限制新手投资
        if (project.getNew_preferential() == 1 && resultUser.getLevel() != 1){
            return ObjectResult.build("0", "您已经购买过，不能再投资新人特惠标！");
        }

        int awardType = 0;
        int awardId = 0;
        BigDecimal redAmount = new BigDecimal(0.00);
        BigDecimal couponInterestRate = new BigDecimal(0.00);
        BigDecimal rateCoupon = project.getUser_interest();

        //加息券红包验证
        if (xmlBean.getAward_id() != null && !xmlBean.getAward_id().equals("") && xmlBean.getAward_type() != null && !xmlBean.getAward_type().equals("")) {

            if (project.getNew_preferential() == 1){
                return ObjectResult.build("0", "新手标不能使用奖励");
            }

            awardType = Integer.parseInt(xmlBean.getAward_type());
            awardId = Integer.parseInt(xmlBean.getAward_id());
            //红包或加息券验证
            if (awardType == 1) {
                // 验证红包相关信息,奖励类型:1红包,2现金券,加息券
                SUserRedenvelope userRed = userRedenvelopeMapper.selectByPrimaryKey(Integer.valueOf(xmlBean.getAward_id()));
                if (userRed == null || userRed.getStatus() != 0) {
                    return ObjectResult.build("0", "系统无法找到红包或红包失效！");
                }
                //红包金额验证
                if (amount.subtract(realMoney).compareTo(userRed.getAmount()) != 0) {
                    ObjectResult.build("0", "红包金额不匹配");
                }

                //最小投资金额验证
                if (amount.compareTo(userRed.getMinInvest()) < 0){
                    return ObjectResult.build("0", "投资金额未达到红包使用要求");
                }
                //最小投资天数验证
                if (project.getDuration() < userRed.getMinDue()){
                    return ObjectResult.build("0", "投资天数未达到红包使用要求");
                }

                redAmount = userRed.getAmount();


            } else if (awardType == 2){
                //验证加息券相关信息,奖励类型:1红包,2现金券,加息券
                SUserInterestCoupon coupon = userInterestCouponMapper.selectByPrimaryKey(Integer.valueOf(xmlBean.getAward_id()));
                if (coupon == null || coupon.getStatus() != 0) {
                    return ObjectResult.build("0", "系统无法找到加息券或券包失效!");
                }

                //加息券金额验证
                Double interestRate = coupon.getInterestRate().doubleValue();
                if (interestRate > 10 || interestRate <= 0) {
                    return ObjectResult.build("0", "加息券金额错误!");
                }

                //最小投资金额验证
                if (amount.compareTo(coupon.getMinInvest()) < 0){
                    return ObjectResult.build("0", "投资金额未达到加息券使用要求");
                }
                //最小投资天数验证
                if (project.getDuration() < coupon.getMinDue()){
                    return ObjectResult.build("0", "投资天数未达到加息券使用要求");
                }
                rateCoupon = rateCoupon.add(coupon.getInterestRate());

            }
        }

        Long user_Id = resultUser.getId();
        Long projectId = Long.parseLong(project.getId());
        BigDecimal awardValue = awardType == 1 ? redAmount : couponInterestRate;
        SUserBank banks = userBankMapper.selectUserBankByUserId(userId);
        if (banks == null || banks.getBankCardNo() == null || banks.getBankCardNo().equals("")){
            return ObjectResult.build("0", "用户未绑定银行卡");
        }
        String bankCardNo = banks.getBankCardNo();
        if (xmlBean.getPay_type().equals("2")){

            //钱包余额判断
            SUserAccount sUserAccount = userAccountMapper.selectAccountAbleWaitInterestByUserId(resultUser.getId());
            if (sUserAccount.getAccount_able().compareTo(realMoney) < 0){
                return ObjectResult.build("0", "钱包余额不足,请充值");
            }

            //钱包余额支付,添加投资记录
            String rechargeNo = p2PMessageUtils.getRechargeNo("W");
            ObjectResult saveRecordsResult = saveRecords(user_Id, projectId, rechargeNo, xmlBean, project.getNew_preferential(),
                    awardType, awardId, amount, awardValue, rateCoupon, 2, bankCardNo);
            if (saveRecordsResult != null){
                return saveRecordsResult;
            }

            //直接添加记录,修改账户余额,没有回调
            ObjectResult objectResult = recordsUtils.saveInvestmentRecordsAndUpdateAccount(user_Id, projectId, rechargeNo, amount, awardId, awardType,
                    awardValue, rateCoupon, 2, project.getNew_preferential(), bankCardNo, 1);
            if (objectResult != null){
                return objectResult;
            }
            HashMap<String, String> hashMap = new HashMap<>();
            hashMap.put("mobile", resultUser.getMobile());
//                hashMap.put("mobile", "13758876025");
            hashMap.put("tpl_id", "138373");
            hashMap.put("key", MobileCodeServiceImpl.SMS_KEY);
            hashMap.put("tpl_value", "#name#="+resultUser.getRealName()+"&#time#="+DateUtil.formatDateTime()+"&#title#="+project.getTitle()+"&#money#="+amount);
            ObjectResult objectResult2 = HttpClientUtil.verificationOfBankCard(MobileCodeServiceImpl.SMS_URL, hashMap);

            return ObjectResult.build("1", "交易成功"/*, resultBean*/);


        }else if (xmlBean.getPay_type().equals("1")){
            //银行卡投资

            String rechargeNo = p2PMessageUtils.getRechargeNo("B");

            //添加投资记录
            ObjectResult saveRecordsResult = saveRecords(user_Id, projectId, rechargeNo, xmlBean, project.getNew_preferential(),
                    awardType, awardId, amount, awardValue, rateCoupon, 1, bankCardNo);
            if (saveRecordsResult != null){
                return saveRecordsResult;
            }

            //返回结果
            ResultBean resultBean = new ResultBean();
            UserInfo userInfo = new UserInfo();
            resultBean.setRecharge_on(rechargeNo);
            userInfo.setReal_name(resultUser.getRealName());
            userInfo.setReal_name_auth(resultUser.getRealNameAuth());
            userInfo.setCard_no(resultUser.getCardNo());
            userInfo.setCard_no_auth(resultUser.getCardNoAuth());
            userInfo.setMobile(resultUser.getMobile());
            userInfo.setType(resultUser.getType());
            userInfo.setLevel(resultUser.getLevel());
            userInfo.setStatus(resultUser.getStatus());
            userInfo.setBank_card_no(bankCardNo);
            userInfo.setBank_code(banks.getBankCode());
            SUserAccount sUserAccount = userAccountMapper.selectAccountAbleWaitInterestByUserId(resultUser.getId());
            userInfo.setAccount_able(sUserAccount.getAccount_able());
            userInfo.setWait_interest(sUserAccount.getWait_interest());
            resultBean.setUserInfo(userInfo);
            resultBean.setUrl(PAGE_NOTIFY_URL + "tender/tenderNotify");

            return ObjectResult.build("1", "", resultBean);

        }

        return ObjectResult.build("0", "网络错误,请稍后重试");

    }


    //保存投资记录,投资前的记录
    public ObjectResult saveRecords(Long userId, Long projectId, String rechargeNo, XMLBean xmlBean, Integer projectType,
                                    Integer awardType, Integer awardId, BigDecimal amoney, BigDecimal awardValue, BigDecimal rateCoupon, Integer rechargeLogStatus, String bankCardNo) {


        //保存投资充值记录
        ObjectResult insertRechargeLogResult = recordsUtils.insertRechargeLog(userId, projectId, rechargeNo, new BigDecimal(xmlBean.getAmoney()), rechargeLogStatus, bankCardNo);
        if (insertRechargeLogResult != null){
            return insertRechargeLogResult;
        }

        //保存详细投资记录
        ObjectResult insertInvestmentDetailResult = recordsUtils.insertInvestmentDetail(userId, projectId, rechargeNo, projectType,
                awardType, awardId, amoney, awardValue, rateCoupon, bankCardNo);
        if (insertInvestmentDetailResult != null){
            return insertInvestmentDetailResult;
        }

        return null;
    }


    //投资回调报文验证,添加回调后校验成功的记录
    @Override
    public ObjectResult verificationTenderNotify(String type, String version, String responsecode, String responsemsg, String mchntcd,
                                                 String mchntorderid, String orderid, String amt, String bankcard, String sign) {

        //验签
        ObjectResult objectResult = new P2PMessageUtils().verificationNotifySign(type, version, responsecode,responsemsg, mchntcd, mchntorderid, orderid, amt, bankcard, sign);
        if (objectResult.getCode().equals("1")){

            SInvestmentDetail SInvestmentDetail = investmentDetailMapper.selectsInvestmentetailByrechargeNo(mchntorderid);
            //返回数据验证
            if (SInvestmentDetail != null){
                //如果使用了红包,减去红包的金额再比较
                BigDecimal invTotal1 = SInvestmentDetail.getInvTotal();
                Integer rewardType = SInvestmentDetail.getRewardType();
                rewardType = rewardType == null?0:rewardType;
                invTotal1 = rewardType == 1?invTotal1.subtract(SInvestmentDetail.getRewardValue()):invTotal1;


                if (version.equals("2.0") && type.equals("02") && (mchntcd.equals(APP_MCHNT_CD))
                        && SInvestmentDetail.getRechargeNo().equals(mchntorderid)
                        && new BigDecimal(amt).compareTo(invTotal1.multiply(BigDecimal.valueOf(100))) == 0){

                    //防止返回重复成功回调,重复添加记录
                    if (SInvestmentDetail.getStatus() == 2){
                        return ObjectResult.build("0", "投资已成功");
                    }


                    //保存成功投资记录并修改钱包余额
                    ObjectResult objectResult1 = recordsUtils.saveInvestmentRecordsAndUpdateAccount(SInvestmentDetail.getUserId(), SInvestmentDetail.getProjectId(), mchntorderid, SInvestmentDetail.getInvTotal(),
                            SInvestmentDetail.getRewardId(), rewardType, SInvestmentDetail.getRewardValue(), SInvestmentDetail.getInterest(), 1, SInvestmentDetail.getBowType(), SInvestmentDetail.getCardNo(), 0);
                    if (objectResult1 != null){
                        return objectResult1;
                    }

                    //设置银行卡已支付
                    SUserBank userBank = new SUserBank();
                    userBank.setUserId(SInvestmentDetail.getUserId());
                    userBank.setModifyTime(new Date());
                    userBank.setHasPaySuccess(2);
                    userBankMapper.updateByUserId(userBank);

                    SUser resultUser = userMapper.selectUserInfoById(SInvestmentDetail.getUserId());
                    SProject project =  projectMapper.selectProjectInfo(SInvestmentDetail.getProjectId());
                    HashMap<String, String> hashMap = new HashMap<>();
                    hashMap.put("mobile", resultUser.getMobile());
                    hashMap.put("tpl_id", "138373");
                    hashMap.put("key", MobileCodeServiceImpl.SMS_KEY);
                    hashMap.put("tpl_value", "#name#="+resultUser.getRealName()+"&#time#="+DateUtil.formatDateTime()+"&#title#="+project.getTitle()+"&#money#="+SInvestmentDetail.getInvTotal());
                    ObjectResult objectResult2 = HttpClientUtil.verificationOfBankCard(MobileCodeServiceImpl.SMS_URL, hashMap);

                    return ObjectResult.build("1", "投资成功");

                }else {
                    return ObjectResult.build("0", "验签失败0x08");
                }

            }else {
                return ObjectResult.build("0", "不存在的投资记录");
            }

        }else {
            return objectResult;
        }

    }



    @Override
    public List<SProject> selectProjectList() {
        return projectMapper.selectProjectList();
    }


    @Override
    public SProject selectProjectByPid(String id) {
        return projectMapper.selectProjectByPid(id);
    }

    @Override
    public List<SProject> selectProjectInvestList(String pid) {
        return projectMapper.selectProjectInvestList(pid);
    }

    @Override
    public List<SProject> selectUserInvestList(Map<String, Object> map) {
        return projectMapper.selectUserInvestList(map);
    }

    @Override
    public SProject selectProjectListLevel1() {
        return projectMapper.selectProjectListLevel1();
    }

    @Override
    public SProject selectProjectListLevel2() {
        return projectMapper.selectProjectListLevel2();
    }

    @Override
    public ObjectResult rank(XMLBean xmlBean) {
        Map<String,Map<String,Object>> map = new HashMap<>();
        Map<String,Object> map2 = new HashMap<>();
        SUser sUser = null;
        if(xmlBean.getToken()!=null){
            sUser = userMapper.selectByPrimaryKey(Long.parseLong(CommonUtils.decToken(xmlBean.getToken())));
        }

        List<SUserDueDetail> list = sUserDueDetailMapper.selectRank();
        int count = 1;//排名
        for (SUserDueDetail sUserDueDetail:list){
            Map<String,Object> data = new HashMap<>();
            data.put("rank",count);
            data.put("amount",sUserDueDetail.getDue_capital());
            count++;
            map.put(sUserDueDetail.getMobile(),data);
        }

        Page<SUserDueDetail> page = new Page<>();
        page.setP(1);
        page.setPageSize(10);
        List<SUserDueDetail> content = page.getPageContent(list);
        count =1;
        for (SUserDueDetail sUserDueDetail:content){
            sUserDueDetail.setRank(count);
            sUserDueDetail.setMobile(CommonUtils.concealMobile(sUserDueDetail.getMobile()));
            count++;
        }
        map2.put("list",content);
        Map<String, Object> pram = new HashMap<>();

        if (map.get(sUser.getMobile())==null ||sUser==null){//未投资或未登录没有排名
            pram.put("rank",0);
            pram.put("amount",new BigDecimal(0));
            map2.put("user",pram);
        }else {
            map2.put("user",map.get(sUser.getMobile()));
        }
        return ObjectResult.build("1","成功",map2);
    }

    @Override
    public ObjectResult loanContract(XMLBean xmlBean) {
        SProject sProject = projectMapper.selectByUserDueDetailId(xmlBean.getId());

        LOGGER.info("user_id:"+sProject.getUserId());
        if(sProject.getContractUrl()!=null&&!"".equals(sProject.getContractUrl())){
            return ObjectResult.build("1","成功","http://api.jsrongdai.cn:8080/"+sProject.getContractUrl());
//            return ObjectResult.build("1","成功","http://admin.jironglicai.com/Uploads/Public/pdf2018-07-21/RJ20180721192127.pdf");
        }
        Map<String, Object> data = new HashMap<>();
        data.put("userId",sProject.getUserId());
        SUser sUser = userMapper.selectUserByMap(data);

        //生成未盖章的合同
        String regNo = PDFHelper.PDFFill(sProject,sUser);

        if (regNo==null){
            return ObjectResult.build("0","导出pdf失败");
        }

        //生成甲方证书
        Map<String,String> map = new HashMap<>();
        map.put("alias",regNo+"alias_1");
        map.put("province",sProject.getProvince());
        map.put("city",sProject.getCity());
        map.put("name", sUser.getRealName());
        map.put("idcard",sUser.getCardNo());
        if(!FxqUtils.GenerateCertificate(map)){
            LOGGER.info("生成甲方证书失败");
            return ObjectResult.build("0","错误0x001");
        };

        //生成乙方证书
        Map<String,String> map2 = new HashMap<>();
        map2.put("alias",regNo+"alias_2");
        map2.put("province","");
        map2.put("city","");
        map2.put("name", sProject.getRealName());
        SUser user = userMapper.selectByPrimaryKey(Long.parseLong(sProject.getUserId()));
        map2.put("idcard",user.getCardNo());

        if(!FxqUtils.GenerateCertificate(map2)){
            LOGGER.info("生成乙方证书失败");
            return ObjectResult.build("0","错误0x001");
        };


        //签署甲方证书到pdf
        map.put("saveName","template2.pdf");
        map.put("fieldName",regNo+"_fieldName1");
        map.put("signPicPath", UtilsGraphics2D.createSeal(sUser.getRealName(),2));//生成印章
        if(!FxqUtils.testSignFirstCertificateToPdf(map)){
            LOGGER.info("签署甲方证书到pdf失败");
            return ObjectResult.build("0","错误0x002");
        }

        String fileName = DateUtil.formatDate();
        createDirectory(FxqUtils.jksSavePath+"/"+fileName);

        //签署乙方证书到pdf
        map2.put("saveName",fileName+"/"+regNo+".pdf");
        map2.put("fieldName",regNo+"_fieldName2");
        map2.put("pdfFileName",map.get("saveName"));
        map2.put("signPicPath", UtilsGraphics2D.createSeal(sProject.getRealName(),1));//生成印章
        if(!FxqUtils.testSignSecondCertificateToPdf(map2)){
            LOGGER.info("签署乙方证书到pdf失败");
            return ObjectResult.build("0","错误0x002");
        }

        SUserDueDetail sUserDueDetail = new SUserDueDetail();
        sUserDueDetail.setId(Long.parseLong(xmlBean.getId()));
        sUserDueDetail.setContractUrl("pdf/"+map2.get("saveName"));
        //添加合同url
        sUserDueDetailMapper.updateByPrimaryKeySelective(sUserDueDetail);

        //删除生成的印章
        DeleteFileUtil.deleteFile(map.get("signPicPath"));
        DeleteFileUtil.deleteFile(map2.get("signPicPath"));

        return ObjectResult.build("1","成功","http://api.jsrongdai.cn:8080/"+sUserDueDetail.getContractUrl());
//        return ObjectResult.build("1","成功","http://admin.jironglicai.com/Uploads/Public/pdf2018-07-21/RJ20180721192127.pdf");
    }

    /***
     * 创建文件夹
     *
     * @param folderPath
     * @return
     */
    public static boolean createDirectory(String folderPath) {
        boolean isSuccess = false;
        File file = new File(folderPath);
        if (!file.exists() && !file.isDirectory()) {
            file.mkdir();
            isSuccess = true;
        } else {
            isSuccess = true;
        }
        return isSuccess;
    }


}

